/*
 * FDSet.cpp
 *
 *  Created on: Jun 27, 2016
 *      Author: Lucifer
 */

#include "FDSet.h"

namespace BFX {

#if PLATFORM == PLATFORM_WINDOWS

FDSet::FDSet(int initialCapacity) :
		_fdSet(nullptr), _capacity(0) {
	capacity(initialCapacity);
}
FDSet::~FDSet() {
	if (_fdSet)
		free(_fdSet);
}
FDSet::operator fd_set*() {
	return (fd_set*) _fdSet;
}
fildes_t FDSet::getMaxDescriptor() const {
	return 0;	// NOTE ignored in windows platform
}
void FDSet::reset() {
	if (_fdSet) {
		_fdSet->fd_count = 0;
	}
}
bool FDSet::set(fildes_t fd) {
	for (u_int i = 0; i < _fdSet->fd_count; i++) {
		if (_fdSet->fd_array[i] == fd)
		return true;	// exists already
	}
	capacity(_fdSet->fd_count + 1);
	_fdSet->fd_array[_fdSet->fd_count++] = fd;
	return true;
}
bool FDSet::isSet(fildes_t fd) const {
	return !!__WSAFDIsSet(fd, (fd_set*) _fdSet);
}

void FDSet::capacity(int size) {
	if (_capacity >= size) {
		return;
	}
	int newCapacity = BFX_MAX(_capacity, 16);
	while (newCapacity < size) {
		newCapacity <<= 1;
	}
	fd_set_t* newFdSet = (fd_set_t*) malloc(
			(sizeof(fd_set_t) - sizeof(SOCKET)) + (sizeof(SOCKET) * newCapacity));
	newFdSet->fd_count = 0;
	if (_fdSet) {
		newFdSet->fd_count = _fdSet->fd_count;
		for (u_int i = 0; i < _fdSet->fd_count; i++) {
			newFdSet->fd_array[i] = _fdSet->fd_array[i];
		}
		free(_fdSet);
	}
	_fdSet = newFdSet;
	_capacity = newCapacity;
}

#else	// !PLATFORM_WINDOWS

FDSet::FDSet() :
		_maxFd((fildes_t) (~0)) {
	FD_ZERO(&_fdSet);
}
FDSet::~FDSet() {
}
FDSet::operator fd_set*() {
	return (&_fdSet);
}
fildes_t FDSet::getMaxDescriptor() const {
	return _maxFd;
}

void FDSet::reset() {
	FD_ZERO(&_fdSet);
}

bool FDSet::set(fildes_t fd) {
	if (fd < FD_SETSIZE) {
		if (_maxFd == (fildes_t) (~0) || fd > _maxFd) {
			_maxFd = fd;
		}
		FD_SET(fd, &_fdSet);
		return true;
	}
	return false;
}
bool FDSet::isSet(fildes_t fd) const {
	return (FD_ISSET(fd, &_fdSet) != 0);
}

#endif	// !PLATFORM_WINDOWS

} /* namespace BFX */
